#include "stdafx.h"

#include "SummaryProperties.h"
#include "DocumentProperties.h"

using namespace System::IO;
using namespace System::Runtime::InteropServices;

using namespace DsoFileNET;

DocumentProperties::DocumentProperties()
{
}

DocumentProperties::~DocumentProperties()
{
	Close(false);
}

void DocumentProperties::Open(String^ fileName, bool readOnly, FileOpenOptions options)
{
	String^ fullPath = System::IO::Path::GetFullPath(fileName);

	if (!File::Exists(fullPath))
		throw gcnew ArgumentException("fileName must point to a valid file");

	FileAttributes fa = File::GetAttributes(fullPath);
	if ((fa & FileAttributes::Offline) == FileAttributes::Offline)
		throw gcnew ArgumentException("fileName is offline and cannot be read");

	DWORD mode = STGM_SHARE_EXCLUSIVE;
	mode |= readOnly ? STGM_READ : STGM_READWRITE;

	if (!readOnly && ((fa & FileAttributes::ReadOnly) == FileAttributes::ReadOnly))
	{
		fa = fa & ~FileAttributes::ReadOnly;
		File::SetAttributes(fullPath, fa);
	}

	IntPtr bstrPtr = Marshal::StringToBSTR(fullPath);
	BSTR bstrFullPath = (BSTR)bstrPtr.ToPointer();

	this->readOnly = readOnly;
	this->options = options;

	HRESULT hr = S_OK;
	if (StgIsStorageFile(bstrFullPath) == S_OK)
	{
		IStorage *tmp = NULL;
		hr = StgOpenStorage(bstrFullPath, NULL, mode, NULL, 0, &tmp);

		if ((hr == STG_E_ACCESSDENIED || hr == STG_E_SHAREVIOLATION) &&
			(options & FileOpenOptions::OpenReadOnlyIfNoWriteAccess) == FileOpenOptions::OpenReadOnlyIfNoWriteAccess)
		{
			readOnly = true;
			hr = StgOpenStorage(bstrFullPath, NULL, (STGM_READ | STGM_TRANSACTED | STGM_SHARE_DENY_NONE), NULL, 0, &tmp);
		}

		Marshal::FreeBSTR(bstrPtr);

		if (SUCCEEDED(hr))
		{
			this->storage.Attach(tmp);
			tmp->Release();
			this->storage.QueryInterface(this->propertyStorage);
		}
	}
	else
	{
		Marshal::FreeBSTR(bstrPtr);
		// we're not currently supporting non-OLE files
		throw gcnew InvalidOperationException("Non-OLE file properties have not been implemented");
	}
}

void DocumentProperties::Close(bool saveBeforeClose)
{
	if (this->summary != nullptr)
		delete this->summary;

	if (this->propertyStorage)
		this->propertyStorage.Release();
	
	if (this->storage)
		this->storage.Release();
}

void DocumentProperties::Save()
{
}

bool DocumentProperties::IsReadOnly::get()
{
	return true;
}

bool DocumentProperties::IsDirty::get()
{
	return true;
}

// SummaryProperties
SummaryProperties^ DocumentProperties::SummaryProperties::get()
{
	if (this->summary == nullptr)
	{
		this->summary = gcnew DsoFileNET::SummaryProperties(this->propertyStorage, this->readOnly, this->options);
	}
	return this->summary;
}

// CustomProperties
Object^ DocumentProperties::CustomProperties::get()
{
	return nullptr;
}

Object^ DocumentProperties::Icon::get()
{
	return nullptr;
}

String^ DocumentProperties::Name::get()
{
	return String::Empty;
}

String^ DocumentProperties::Path::get()
{
	return String::Empty;
}

bool DocumentProperties::IsOleFile::get()
{
	return false;
}

String^ DocumentProperties::ClassId::get()
{
	return String::Empty;
}

String^ DocumentProperties::ProgId::get()
{
	return String::Empty;
}

String^ DocumentProperties::OleDocumentFormat::get()
{
	return String::Empty;
}

String^ DocumentProperties::OleDocumentType::get()
{
	return String::Empty;
}
